package com.gzyj.server.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzyj.pojo.gps.YjGpsAddr;
import com.gzyj.server.config.LogConfig;
import com.gzyj.server.mapper.YjGpsAddrMapper;
import com.gzyj.server.utils.StackUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;

@Service
public class YjGpsAddrService {
    @Autowired
    private RestTemplate restTemplate;

    @Value("${isOpenSearchGPS}")
    private boolean isOpenSearchGPS;

    @Resource(name = "clusterRedisTemplate")
    private RedisTemplate<String, Object> clusterRedisTemplate;


    public String getAddress(double lat, double lng) {
        if(isOpenSearchGPS){
            try {
                DecimalFormat decimalFormat = new DecimalFormat("0.000000");
                String key = "map-location:" + decimalFormat.format(new BigDecimal(lat)) + "-" + decimalFormat.format(new BigDecimal(lng)) + "*";
                if (CollectionUtil.isNotEmpty(clusterRedisTemplate.keys(key))) {
                    return (String) clusterRedisTemplate.opsForValue().get(key);
                } else {
                    try {
                        //腾讯
                        ResponseEntity<String> resp = restTemplate.getForEntity("https://apis.map.qq.com/ws/geocoder/v1/?location=" + lat + "," + lng + "&key=LPJBZ-HPCCK-HCTJM-AZYZ4-FACS2-SRB4M", String.class);

                        JSONObject param = JSON.parseObject(resp.getBody());
                        if (param.getInteger("status") == 0) {

                            JSONObject result = param.getJSONObject("result");

                            YjGpsAddr gpsAddr = new YjGpsAddr();
                            gpsAddr.setLat(lat);
                            gpsAddr.setLng(lng);

                            gpsAddr.setProvince(result.getJSONObject("ad_info").getString("province"));
                            gpsAddr.setCity(result.getJSONObject("ad_info").getString("city"));
                            gpsAddr.setCitycode(result.getJSONObject("ad_info").getString("city_code"));
                            gpsAddr.setDistrict(result.getJSONObject("ad_info").getString("district"));
                            gpsAddr.setAdcode(result.getJSONObject("ad_info").getString("adcode"));
                            if (result.containsKey("address_reference") && result.getJSONObject("address_reference").containsKey("town")
                                    && result.getJSONObject("address_reference").getJSONObject("town").containsKey("title"))
                                gpsAddr.setTownship(result.getJSONObject("address_reference").getJSONObject("town").getString("title"));

                            gpsAddr.setFormattedAddress(result.getString("address"));
                            saveOrUpdateByMultiId(gpsAddr);
                            clusterRedisTemplate.opsForValue().set(key, gpsAddr.getFormattedAddress());
                            return gpsAddr.getFormattedAddress();

                        } else {
                            //高德
                            resp = restTemplate.getForEntity("https://restapi.amap.com/v3/geocode/regeo?location=" + lng + "," + lat + "&key=9d42b66a5566031cc7bae64c53a399e7", String.class);
                            param = JSON.parseObject(resp.getBody());
                            if (param.getString("status").equals("1")) {

                                JSONObject result = param.getJSONObject("regeocode");

                                YjGpsAddr gpsAddr = new YjGpsAddr();
                                gpsAddr.setLat(lat);
                                gpsAddr.setLng(lng);

                                gpsAddr.setProvince(result.getJSONObject("addressComponent").getString("province"));
                                gpsAddr.setCity(result.getJSONObject("addressComponent").getString("city"));
                                gpsAddr.setCitycode(result.getJSONObject("addressComponent").getString("citycode"));
                                gpsAddr.setDistrict(result.getJSONObject("addressComponent").getString("district"));
                                gpsAddr.setAdcode(result.getJSONObject("addressComponent").getString("adcode"));
                                gpsAddr.setTownship(result.getJSONObject("addressComponent").getString("township"));
                                gpsAddr.setTowncode(result.getJSONObject("addressComponent").getString("towncode"));
                                gpsAddr.setFormattedAddress(result.getString("formatted_address"));
                                saveOrUpdateByMultiId(gpsAddr);
                                clusterRedisTemplate.opsForValue().set(key, gpsAddr.getFormattedAddress());
                                return gpsAddr.getFormattedAddress();

                            } else {
                                //百度
                                resp = restTemplate.getForEntity("https://api.map.baidu.com/reverse_geocoding/v3/?ak=C02c9cf83d7a1705126e570e38b07171&output=json&coordtype=gcj02ll&location=" + lat + "," + lng, String.class);
                                param = JSON.parseObject(resp.getBody());
                                if (param.getInteger("status") == 0) {
                                    JSONObject result = param.getJSONObject("result");

                                    YjGpsAddr gpsAddr = new YjGpsAddr();
                                    gpsAddr.setLat(lat);
                                    gpsAddr.setLng(lng);

                                    gpsAddr.setProvince(result.getJSONObject("addressComponent").getString("province"));
                                    gpsAddr.setCity(result.getJSONObject("addressComponent").getString("city"));
                                    gpsAddr.setCitycode(result.getInteger("cityCode") + "");
                                    gpsAddr.setDistrict(result.getJSONObject("addressComponent").getString("district"));
                                    gpsAddr.setAdcode(result.getJSONObject("addressComponent").getString("adcode"));
                                    gpsAddr.setTownship(result.getJSONObject("addressComponent").getString("town"));
                                    gpsAddr.setTowncode(result.getJSONObject("addressComponent").getString("town_code"));
                                    gpsAddr.setFormattedAddress(result.getString("formatted_address"));
                                    saveOrUpdateByMultiId(gpsAddr);
                                    clusterRedisTemplate.opsForValue().set(key, gpsAddr.getFormattedAddress());
                                    return gpsAddr.getFormattedAddress();
                                }
                            }
                        }
                    } catch (Exception e) {
                        LogConfig.locationErrorLog.error("调取gps解析接口错误 \n {}", StackUtils.getStackInfo(e));
                        return "未知道路";
                    }

                }
            } catch (Exception e) {
                LogConfig.locationErrorLog.error("gps获取错误 {} {} \n {}", lat, lng, StackUtils.getStackInfo(e));
                return "未知道路";
            }
            return "未知道路";
        }else{
            return "未知道路";
        }

    }

    @Autowired
    private YjGpsAddrMapper yjGpsAddrMapper;

    private void saveOrUpdateByMultiId(YjGpsAddr gpsAddr) {

        QueryWrapper<YjGpsAddr> w = new QueryWrapper<>();
        w.eq("lat", gpsAddr.getLat());
        w.eq("lng", gpsAddr.getLng());

        int count = yjGpsAddrMapper.selectList(w).size();

        if (count > 0) {
            return;
        } else {
            try {
                yjGpsAddrMapper.insert(gpsAddr);
            } catch (Exception e) {
                return;
            }

        }


    }


}
